<script setup lang="ts">
import type { FormInstance } from 'ant-design-vue';

import type { Menu } from '#/api';

import { computed, reactive, ref, watch } from 'vue';

import {
  Form,
  FormItem,
  Input,
  InputNumber,
  message,
  Modal,
  Radio,
  RadioGroup,
  TreeSelect,
} from 'ant-design-vue';

import { addMenuApi, getMenuTreeApi, MenuType, updateMenuApi } from '#/api';
import IconPicker from '#/components/icon-picker/index.vue';
import { prepareCreateData, prepareUpdateData } from '#/utils/form';

interface Props {
  visible: boolean;
  menuData?: Menu;
  parentMenu?: Menu; // 新增：父菜单（用于新增下级菜单）
}

const props = defineProps<Props>();
const emit = defineEmits(['update:visible', 'success']);

const formRef = ref<FormInstance>();
const confirmLoading = ref(false);
const parentMenuOptions = ref<Menu[]>([]);

// 是否编辑模式
const isEdit = computed(() => !!props.menuData?.id);

// 表单数据
const formData = reactive<Menu>({
  id: undefined,
  parentId: 0,
  menuName: '',
  menuType: MenuType.MENU,
  path: '',
  component: '',
  permission: '',
  icon: '',
  sort: 0,
  visible: 1,
  link: '',
});

// 表单验证规则
const rules = {
  menuName: [{ required: true, message: '请输入菜单名称', trigger: 'blur' }],
  menuType: [{ required: true, message: '请选择菜单类型', trigger: 'change' }],
  path: [
    {
      required: true,
      message: '请输入路由路径',
      trigger: 'blur',
      validator: (_rule: any, value: string) => {
        if (formData.menuType === MenuType.BUTTON) {
          return Promise.resolve();
        }
        if (!value) {
          return Promise.reject(new Error('请输入路由路径'));
        }
        return Promise.resolve();
      },
    },
  ],
};

// 监听弹窗显示状态，每次打开时重新获取父菜单数据
watch(
  () => props.visible,
  (newVal) => {
    if (newVal) {
      // 弹窗打开时，重新获取最新的父菜单数据
      fetchParentMenuOptions();
    }
  },
);

// 监听菜单数据变化
watch(
  () => props.menuData,
  (newVal) => {
    if (newVal) {
      Object.assign(formData, newVal);
    } else {
      resetForm();
    }
  },
  { immediate: true },
);

// 监听父菜单变化（用于新增下级菜单）
watch(
  () => props.parentMenu,
  (newVal) => {
    if (newVal && !props.menuData) {
      // 只在新增模式下设置父菜单
      formData.parentId = newVal.id || 0;
    }
  },
  { immediate: true },
);

// 重置表单
function resetForm() {
  formData.id = undefined;
  formData.parentId = 0;
  formData.menuName = '';
  formData.menuType = MenuType.MENU;
  formData.path = '';
  formData.component = '';
  formData.permission = '';
  formData.icon = '';
  formData.sort = 0;
  formData.visible = 1;
  formData.link = '';
  formRef.value?.clearValidate();
}

// 过滤掉按钮类型的菜单（按钮不能作为父菜单）
function filterButtonMenus(menus: Menu[]): Menu[] {
  return menus
    .filter((menu) => menu.menuType !== MenuType.BUTTON && menu.menuType !== 'BUTTON' && menu.menuType !== 3)
    .map((menu) => ({
      ...menu,
      children: menu.children ? filterButtonMenus(menu.children) : undefined,
    }));
}

// 获取父级菜单选项
async function fetchParentMenuOptions() {
  try {
    const data = await getMenuTreeApi();
    // 过滤掉按钮类型的菜单
    const filteredData = filterButtonMenus(data);
    // 添加顶级菜单选项
    parentMenuOptions.value = [
      {
        id: 0,
        parentId: 0,
        menuName: '顶级菜单',
        menuType: MenuType.DIRECTORY,
        children: filteredData,
      },
    ];
  } catch {
    message.error('获取父级菜单失败');
  }
}

// 确定
async function handleOk() {
  try {
    await formRef.value?.validate();
    confirmLoading.value = true;

    if (isEdit.value) {
      // 编辑：移除审计字段
      await updateMenuApi(prepareUpdateData(formData) as Menu);
      message.success('编辑成功');
    } else {
      // 新增：移除审计字段和 id
      await addMenuApi(prepareCreateData(formData) as Menu);
      message.success('新增成功');
    }

    emit('success');
    handleCancel();
  } catch {
    // 验证失败或请求失败
  } finally {
    confirmLoading.value = false;
  }
}

// 取消
function handleCancel() {
  emit('update:visible', false);
  resetForm();
}
</script>

<template>
  <Modal
    :visible="visible"
    :title="isEdit ? '编辑菜单' : '新增菜单'"
    :confirm-loading="confirmLoading"
    @ok="handleOk"
    @cancel="handleCancel"
  >
    <Form
      ref="formRef"
      :model="formData"
      :rules="rules"
      :label-col="{ span: 6 }"
      :wrapper-col="{ span: 16 }"
    >
      <FormItem label="父级菜单" name="parentId">
        <TreeSelect
          v-model:value="formData.parentId"
          :tree-data="parentMenuOptions"
          placeholder="请选择父级菜单"
          :field-names="{
            label: 'menuName',
            value: 'id',
            children: 'children',
          }"
          tree-default-expand-all
          allow-clear
        />
      </FormItem>

      <FormItem label="菜单名称" name="menuName">
        <Input v-model:value="formData.menuName" placeholder="请输入菜单名称" />
      </FormItem>

      <FormItem label="菜单类型" name="menuType">
        <RadioGroup v-model:value="formData.menuType">
          <Radio :value="MenuType.DIRECTORY">目录</Radio>
          <Radio :value="MenuType.MENU">菜单</Radio>
          <Radio :value="MenuType.BUTTON">按钮</Radio>
        </RadioGroup>
      </FormItem>

      <FormItem
        v-if="formData.menuType !== MenuType.BUTTON"
        label="路由路径"
        name="path"
      >
        <Input v-model:value="formData.path" placeholder="请输入路由路径" />
      </FormItem>

      <FormItem
        v-if="formData.menuType === MenuType.MENU"
        label="组件路径"
        name="component"
      >
        <Input
          v-model:value="formData.component"
          placeholder="请输入组件路径"
        />
      </FormItem>

      <FormItem
        v-if="formData.menuType !== MenuType.BUTTON"
        label="外链地址"
        name="link"
      >
        <Input
          v-model:value="formData.link"
          placeholder="请输入外链地址（如：http://localhost:11500/system/doc.html）"
        />
        <template #extra>
          <span class="text-xs text-gray-500">
            配置外链后，点击菜单将在新窗口打开该链接。留空则使用组件路径
          </span>
        </template>
      </FormItem>

      <FormItem label="权限标识" name="permission">
        <Input
          v-model:value="formData.permission"
          placeholder="请输入权限标识（如：sys:menu:add）"
        />
        <template #extra>
          <span class="text-xs text-gray-500">
            用于后端权限控制，格式建议：模块:功能:操作（如：sys:menu:add、sys:user:edit）
          </span>
        </template>
      </FormItem>

      <FormItem
        v-if="formData.menuType !== MenuType.BUTTON"
        label="菜单图标"
        name="icon"
      >
        <IconPicker v-model:value="formData.icon" />
      </FormItem>

      <FormItem label="排序号" name="sort">
        <InputNumber
          v-model:value="formData.sort"
          :min="0"
          placeholder="请输入排序号"
          style="width: 100%"
        />
      </FormItem>

      <FormItem
        v-if="formData.menuType !== MenuType.BUTTON"
        label="是否显示"
        name="visible"
      >
        <RadioGroup v-model:value="formData.visible">
          <Radio :value="1">显示</Radio>
          <Radio :value="0">隐藏</Radio>
        </RadioGroup>
      </FormItem>
    </Form>
  </Modal>
</template>
